<script lang="tsx">
import { defineComponent, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import { $t } from '@vben/locales';
import { ChevronDown, ChevronRight, ChevronLeft } from '@vben/icons';

import { VbenIcon } from '@vben-core/shadcn-ui';

// 树节点接口
export interface TreeNode {
  id: string;
  name: string;
  createTime?: string;
  pid?: string;
  children?: TreeNode[];
}

export default defineComponent({
  name: 'TreeSelector',
  props: {
    // 数据获取函数
    fetchData: {
      type: Function,
      required: true,
    },
    // 当前选中的值
    modelValue: {
      type: String,
      default: '',
    },
    // 是否显示全部选项
    showAll: {
      type: Boolean,
      default: true,
    },
    // 全部选项的文本
    allText: {
      type: String,
      default: '全部',
    },
    // 全部选项的值
    allValue: {
      type: String,
      default: '',
    },
  },
  emits: ['update:modelValue', 'change'],
  setup(props, { emit }) {
    const loading = ref(false);
    const treeData = ref<TreeNode[]>([]);
    const expandedKeys = ref<Set<string>>(new Set());
    const selectedKey = ref(props.modelValue);
    const selectedPath = ref<TreeNode[]>([]);

    // 每级容器引用与箭头可见性状态
    const levelContainerRefs = ref<Record<number, HTMLDivElement | null>>({});
    const levelScrollState = ref<Record<number, { canLeft: boolean; canRight: boolean }>>({});

    const updateLevelArrowState = (level: number) => {
      const el = levelContainerRefs.value[level];
      if (!el) return;
      const canLeft = el.scrollLeft > 0;
      const canRight = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
      levelScrollState.value[level] = { canLeft, canRight };
    };

    const updateAllArrowStates = () => {
      const max = getMaxLevel() + 1;
      for (let i = 0; i < max; i++) updateLevelArrowState(i);
    };

    const scrollOnePage = (level: number, direction: 'left' | 'right') => {
      const el = levelContainerRefs.value[level];
      if (!el) return;
      const page = Math.max(120, Math.floor(el.clientWidth * 0.9));
      const nextLeft = direction === 'left' ? el.scrollLeft - page : el.scrollLeft + page;
      el.scrollTo({ left: nextLeft, behavior: 'smooth' });
      requestAnimationFrame(() => updateLevelArrowState(level));
    };

    // 获取树形数据
    const fetchTreeData = async () => {
      loading.value = true;
      try {
        const data = await props.fetchData();
        treeData.value = data || [];
        // 默认展开第一级
        data?.forEach((item: TreeNode) => {
          if (item.children && item.children.length > 0) {
            expandedKeys.value.add(item.id);
          }
        });
      } catch (error) {
        console.error('Failed to fetch tree data:', error);
        treeData.value = [];
      } finally {
        loading.value = false;
      }
    };

    // 切换展开/收起
    const toggleExpand = (nodeId: string) => {
      if (expandedKeys.value.has(nodeId)) {
        expandedKeys.value.delete(nodeId);
      } else {
        expandedKeys.value.add(nodeId);
      }
    };

    // 选择节点
    const selectNode = (nodeId: string, nodeName: string, node?: TreeNode) => {
      selectedKey.value = nodeId;

      // 更新选中路径
      if (nodeId === props.allValue) {
        selectedPath.value = [];
      } else if (node) {
        selectedPath.value = getNodePath(node, treeData.value);
      }

      emit('update:modelValue', nodeId);
      emit('change', nodeId, nodeName);
    };

    // 获取节点路径
    const getNodePath = (
      targetNode: TreeNode,
      nodes: TreeNode[],
      path: TreeNode[] = [],
    ): TreeNode[] => {
      for (const node of nodes) {
        const currentPath = [...path, node];
        if (node.id === targetNode.id) {
          return currentPath;
        }
        if (node.children && node.children.length > 0) {
          const childPath = getNodePath(targetNode, node.children, currentPath);
          if (childPath.length > 0) {
            return childPath;
          }
        }
      }
      return [];
    };

    // 获取指定级别的节点
    const getNodesAtLevel = (level: number): TreeNode[] => {
      if (level === 0) {
        return treeData.value;
      }

      if (selectedPath.value.length >= level) {
        const parentNode = selectedPath.value[level - 1];
        return parentNode?.children || [];
      }

      return [];
    };

    // 获取最大层级数
    const getMaxLevel = (): number => {
      const getDepth = (nodes: TreeNode[], currentDepth = 0): number => {
        let maxDepth = currentDepth;
        for (const node of nodes) {
          if (node.children && node.children.length > 0) {
            maxDepth = Math.max(
              maxDepth,
              getDepth(node.children, currentDepth + 1),
            );
          }
        }
        return maxDepth;
      };

      return Math.max(selectedPath.value.length, getDepth(treeData.value));
    };

    // 判断节点是否在选中路径中
    const isNodeInPath = (nodeId: string, level: number): boolean => {
      return (
        selectedPath.value.length > level &&
        selectedPath.value?.[level]?.id === nodeId
      );
    };

    // 判断节点是否为最终选中的节点
    const isNodeSelected = (nodeId: string): boolean => {
      return selectedKey.value === nodeId;
    };

    // 渲染树节点
    const renderTreeNode = (node: TreeNode, level: number = 0) => {
      const hasChildren = node.children && node.children.length > 0;
      const isExpanded = expandedKeys.value.has(node.id);
      const isSelected = selectedKey.value === node.id;

      return (
        <div class="tree-node" key={node.id}>
          <div
            class={`flex cursor-pointer items-center rounded-lg px-3 py-2 transition-all duration-200 ${isSelected
              ? 'bg-blue-50 font-medium text-blue-600'
              : 'text-gray-700 hover:bg-gray-50'
              }`}
            onClick={() => selectNode(node.id, node.name)}
            style={{ paddingLeft: `${level * 20 + 12}px` }}
          >
            {hasChildren && (
              <div
                class="mr-2 flex h-4 w-4 cursor-pointer items-center justify-center"
                onClick={(e) => {
                  e.stopPropagation();
                  toggleExpand(node.id);
                }}
              >
                <VbenIcon
                  class="h-3 w-3 fill-transparent text-gray-500 transition-transform duration-200"
                  icon={isExpanded ? ChevronDown : ChevronRight}
                />
              </div>
            )}
            {!hasChildren && <div class="mr-2 h-4 w-4"></div>}
            <span class="flex-1 text-sm">{node.name}</span>
          </div>
          {hasChildren && isExpanded && (
            <div class="children">
              {node.children!.map((child) => renderTreeNode(child, level + 1))}
            </div>
          )}
        </div>
      );
    };

    onMounted(() => {
      fetchTreeData();
      window.addEventListener('resize', updateAllArrowStates);
    });

    onUnmounted(() => {
      window.removeEventListener('resize', updateAllArrowStates);
    });

    watch([treeData, selectedPath], () => {
      nextTick(() => updateAllArrowStates());
    }, { deep: true });

    return () => (
      <div class="tree-selector rounded-[16px] border px-[16px] py-[16px] bg-white">
        {loading.value ? (
          <div class="flex items-center justify-center">
            <div class="animate-spin rounded-full h-6 w-6 border-b-2 border-[#0067D1]"></div>
            <span class="ml-2 text-[16px] text-[#595959] leading-[22px]">{$t('course.loading')}</span>
          </div>
        ) : (
          <div class="flex items-start gap-[24px]">
            {/* 左侧标签 */}
            <div class="flex-shrink-0 text-[16px] text-[#595959] leading-[32px] whitespace-nowrap">{$t('course.subjectCategory')}</div>

            {/* 右侧分类选择区域 */}
            <div class="flex-1 min-w-0 flex flex-col gap-[8px]">
              {/* 动态渲染各级分类 */}
              {Array.from({ length: getMaxLevel() + 1 }, (_, level) => {
                const nodesAtLevel = getNodesAtLevel(level);
                if (nodesAtLevel.length === 0) return null;

                return (
                  <div key={level}>
                    <div class="relative px-[48px]">
                      {levelScrollState.value?.[level]?.canLeft && (
                        <button
                          class="absolute left-[8px] top-1/2 -translate-y-1/2 z-10 h-[16px] w-[16px] rounded-full bg-[#191919] text-white hover:bg-[#0067D1] flex items-center justify-center"
                          onClick={() => scrollOnePage(level, 'left')}
                          aria-label="scroll-left"
                        >
                          <VbenIcon class="h-full w-full" icon={ChevronLeft} />
                        </button>
                      )}

                      <div
                        class="overflow-x-auto overflow-y-hidden no-scrollbar"
                        ref={(el) => (levelContainerRefs.value[level] = el as HTMLDivElement)}
                        onScroll={() => updateLevelArrowState(level)}
                      >
                        <div class="flex min-w-max">
                          {/* 全部选项行 - 只在第一级显示 */}
                          {props.showAll && level === 0 && (
                            <span
                              class={`flex-shrink-0 cursor-pointer rounded-full text-[16px] leading-[26px] px-[15px] transition-all duration-200 flex items-center whitespace-nowrap ${selectedKey.value === props.allValue
                                ? 'bg-[#0067D1] text-white'
                                : 'bg-white hover:bg-[#0067D1] hover:text-white'
                                }`}
                              onClick={() => selectNode(props.allValue, props.allText)}
                            >
                              {props.allText}
                            </span>
                          )}
                          {nodesAtLevel.map((node, index) => {
                            const isInPath = isNodeInPath(node.id, level);
                            const isSelected = isNodeSelected(node.id);
                            const isLastNode = index === nodesAtLevel.length - 1;

                            return (
                              <span
                                class={`flex-shrink-0 cursor-pointer transition-all duration-200 flex items-center whitespace-nowrap px-[15px] py-[3px] ${level === 0 ? 'text-[16px] leading-[26px] rounded-full' : 'text-[14px] '
                                  } ${level === 0
                                    ? (
                                      isSelected
                                        ? 'bg-[#0067D1] text-white'
                                        : isInPath
                                          ? 'bg-[#0067D1] text-white'
                                          : 'bg-white hover:bg-[#0067D1] hover:text-white'
                                    )
                                    : (
                                      isSelected
                                        ? 'text-[#0067D1]'
                                        : isInPath
                                          ? 'text-[#0067D1]'
                                          : 'hover:text-[#0067D1]'
                                    )
                                  } ${level > 0 && !isLastNode ? 'border-r border-gray-300' : ''}`}
                                key={node.id}
                                onClick={() => selectNode(node.id, node.name, node)}
                              >
                                {node.name}
                              </span>
                            );
                          })}
                        </div>
                      </div>

                      {levelScrollState.value?.[level]?.canRight && (
                        <button
                          class="absolute right-[8px] top-1/2 -translate-y-1/2 z-10 h-[16px] w-[16px] rounded-full bg-[#191919] text-white hover:bg-[#0067D1] flex items-center justify-center"
                          onClick={() => scrollOnePage(level, 'right')}
                          aria-label="scroll-right"
                        >
                          <VbenIcon class="h-full w-full" icon={ChevronRight} />
                        </button>
                      )}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        )}
      </div>
    )
  }
})
</script>

<style scoped>
/* 自定义滚动条样式 */
.scrollbar-thin::-webkit-scrollbar {
  height: 4px;
}

.scrollbar-track-gray-100::-webkit-scrollbar-track {
  background: #f3f4f6;
  border-radius: 2px;
}

.scrollbar-thumb-gray-300::-webkit-scrollbar-thumb {
  background: #d1d5db;
  border-radius: 2px;
}

.hover\:scrollbar-thumb-gray-400::-webkit-scrollbar-thumb:hover {
  background: #9ca3af;
}

/* 隐藏滚动条（跨浏览器） */
.no-scrollbar::-webkit-scrollbar {
  display: none;
}

.no-scrollbar {
  -ms-overflow-style: none;
  scrollbar-width: none;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .flex.items-start.gap-4 {
    flex-direction: column;
    gap: 0.5rem;
  }

  .leading-10 {
    line-height: normal;
  }

  .h-10 {
    height: 2.25rem;
    font-size: 0.8125rem;
    padding: 0 0.75rem;
  }

  .h-8 {
    height: 1.75rem;
    font-size: 0.75rem;
    padding: 0 0.625rem;
  }
}
</style>
